﻿@using AliasVault.Shared.Models.Spamok
@using AliasVault.Shared.Utilities
@using AliasVault.Shared.Core;
@using AliasVault.Client.Main.Components.Layout
@using AliasVault.RazorComponents.Services
@using Microsoft.Extensions.Localization
@inject JsInteropService JsInteropService
@inject GlobalNotificationService GlobalNotificationService
@inject IHttpClientFactory HttpClientFactory
@inject EmailService EmailService
@inject HttpClient HttpClient
@inject ConfirmModalService ConfirmModalService
@inject IStringLocalizerFactory LocalizerFactory

<ClickOutsideHandler OnClose="OnClose" ContentId="emailModal">
    <ModalWrapper OnEnter="Close">
        <div id="emailModal" class="relative bg-white w-3/4 flex flex-col rounded-lg shadow-xl max-h-[90vh] border-2 border-gray-300 dark:border-gray-400">
            <!-- Header -->
            <div class="p-4 border-b">
                <div class="flex items-center justify-between mb-3">
                    <h2 class="text-2xl font-bold text-gray-900">
                        @if (IsSpamOk)
                        {
                            <a target="_blank" href="https://spamok.com/@(Email!.ToLocal)/@(Email!.Id)">@Email.Subject</a>
                        }
                        else
                        {
                            <span>@Email?.Subject</span>
                        }
                    </h2>
                    <button @onclick="Close" class="text-gray-400 hover:text-gray-500">
                        <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                        </svg>
                    </button>
                </div>
                <!-- 2-column layout for email details -->
                <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm text-gray-500 dark:text-gray-400">
                    <div class="space-y-1">
                        <p>@Localizer["FromLabel"] @(Email?.FromLocal)@@@(Email?.FromDomain)</p>
                        <p>@Localizer["ToLabel"] @(Email?.ToLocal)@@@(Email?.ToDomain)</p>
                    </div>
                    <div class="space-y-1">
                        <p>@Localizer["DateLabel"] @Email?.DateSystem</p>
                        <p>@Localizer["ActionsLabel"] <button @onclick="ShowDeleteConfirmation" class="text-red-500 hover:text-red-700 text-sm">@Localizer["DeleteButton"]</button></p>
                    </div>
                </div>
            </div>

            <!-- Scrollable Content -->
            <div class="flex-1 overflow-y-auto p-4">
                <div class="text-gray-700 dark:text-gray-300">
                    <div>
                        <iframe class="w-full overscroll-y-auto" style="height:500px;" srcdoc="@EmailBody">
                        </iframe>
                    </div>
                </div>
                <div class="mt-4">
                    @if (Email?.Attachments?.Any() == true)
                    {
                        <div class="border-t border-gray-200 dark:border-gray-600 pt-4">
                            <h3 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-2">@Localizer["AttachmentsLabel"]</h3>
                            <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
                                @foreach (var attachment in Email.Attachments)
                                {
                                    <div class="flex items-center space-x-2">
                                        <svg class="w-4 h-4 text-gray-500 dark:text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"></path>
                                        </svg>
                                        <button @onclick="() => DownloadAttachment(attachment)"
                                                class="text-primary hover:underline text-sm truncate attachment-link">
                                            (@(Math.Ceiling((double)attachment.Filesize / 1024)) KB) @attachment.Filename
                                        </button>
                                    </div>
                                }
                            </div>
                        </div>
                    }
                </div>
                <div class="mt-6 flex justify-end space-x-4">
                    <button id="close-email-modal" @onclick="Close" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">@Localizer["CloseButton"]</button>
                </div>
            </div>
        </div>
    </ModalWrapper>
</ClickOutsideHandler>

@code {
    private IStringLocalizer Localizer => LocalizerFactory.Create("Components.Main.Email.EmailModal", "AliasVault.Client");

    private IStringLocalizer SharedLocalizer => LocalizerFactory.Create("SharedResources", "AliasVault.Client");

    /// <summary>
    /// The email to show in the modal.
    /// </summary>
    [Parameter]
    public EmailApiModel? Email { get; set; }

    /// <summary>
    /// Boolean that indicates if the email is from SpamOK public API.
    /// </summary>
    [Parameter]
    public bool IsSpamOk { get; set; }

    /// <summary>
    /// Callback when the modal is closed.
    /// </summary>
    [Parameter]
    public EventCallback<bool> OnClose { get; set; }

    /// <summary>
    /// Callback when an email is deleted.
    /// </summary>
    [Parameter]
    public EventCallback<int> OnEmailDeleted { get; set; }

    /// <summary>
    /// The message body to display
    /// </summary>
    private string EmailBody = string.Empty;

    /// <summary>
    /// Show confirmation modal before deleting email.
    /// </summary>
    private async Task ShowDeleteConfirmation()
    {
        if (Email == null)
        {
            return;
        }

        var result = await ConfirmModalService.ShowConfirmation(
            Localizer["DeleteEmailTitle"],
            Localizer["DeleteEmailConfirmation"],
            SharedLocalizer["Confirm"],
            SharedLocalizer["Cancel"]
        );

        if (result)
        {
            await DeleteEmail();
        }
    }

    /// <summary>
    /// Close the modal.
    /// </summary>
    [JSInvokable]
    public Task Close()
    {
        return OnClose.InvokeAsync(false);
    }

    /// <summary>
    /// Delete the current email.
    /// </summary>
    private async Task DeleteEmail()
    {
        if (Email == null)
        {
            return;
        }

        if (IsSpamOk)
        {
            await DeleteEmailSpamOk();
        }
        else
        {
            await DeleteEmailAliasVault();
        }
    }

    /// <summary>
    /// Delete the current email in SpamOk.
    /// </summary>
    private async Task DeleteEmailSpamOk()
    {
        if (Email == null)
        {
            return;
        }

        try
        {
            var client = HttpClientFactory.CreateClient("EmailClient");
            var request = new HttpRequestMessage(HttpMethod.Delete, $"https://api.spamok.com/v2/Email/{Email.ToLocal}/{Email.Id}");
            request.Headers.Add("X-Asdasd-Platform-Id", "av-web");
            request.Headers.Add("X-Asdasd-Platform-Version", AppInfo.GetFullVersion());

            var response = await client.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                await OnEmailDeleted.InvokeAsync(Email.Id);
                GlobalNotificationService.AddSuccessMessage(Localizer["EmailDeletedSuccess"], true);
                await Close();
            }
            else
            {
                var errorMessage = await response.Content.ReadAsStringAsync();
                GlobalNotificationService.AddErrorMessage($"{Localizer["EmailDeleteFailed"]}: {errorMessage}", true);
            }
        }
        catch (Exception ex)
        {
            GlobalNotificationService.AddErrorMessage($"{Localizer["GenericError"]}: {ex.Message}", true);
        }
    }

    /// <summary>
    /// Delete the current email in AliasVault.
    /// </summary>
    private async Task DeleteEmailAliasVault()
    {
        if (Email == null)
        {
            return;
        }

        try
        {
            var response = await HttpClient.DeleteAsync($"v1/Email/{Email.Id}");
            if (response.IsSuccessStatusCode)
            {
                await OnEmailDeleted.InvokeAsync(Email.Id);
                GlobalNotificationService.AddSuccessMessage(Localizer["EmailDeletedSuccess"], true);
            }
            else
            {
                GlobalNotificationService.AddErrorMessage(Localizer["EmailDeleteFailed"], true);
            }
        }
        catch (Exception ex)
        {
            GlobalNotificationService.AddErrorMessage($"{Localizer["EmailDeleteFailed"]}: {ex.Message}", true);
        }
    }

    /// <inheritdoc />
    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        // Determine email body
        if (Email != null)
        {
            // Check if there is HTML content, if not, then set default viewtype to plain
            if (Email.MessageHtml is not null && !string.IsNullOrWhiteSpace(Email.MessageHtml))
            {
                // HTML is available
                EmailBody = ConversionUtility.ConvertAnchorTagsToOpenInNewTab(Email.MessageHtml);
            }
            else if (Email.MessagePlain is not null)
            {
                // No HTML but plain text is available
                // Escape HTML entities and wrap in pre tag to preserve formatting
                var escapedText = System.Net.WebUtility.HtmlEncode(Email.MessagePlain);
                EmailBody = $"<pre style='font-family: system-ui, -apple-system, sans-serif; white-space: pre-wrap; word-wrap: break-word; margin: 0;'>{escapedText}</pre>";
            }
            else
            {
                // No HTML and no plain text available
                EmailBody = Localizer["NoEmailBody"];
            }
        }
    }

    /// <summary>
    /// Download an attachment.
    /// </summary>
    private async Task DownloadAttachment(AttachmentApiModel attachment)
    {
        try
        {
            if (IsSpamOk)
            {
                var client = HttpClientFactory.CreateClient("EmailClient");
                var request = new HttpRequestMessage(HttpMethod.Get, $"https://api.spamok.com/v2/Attachment/{Email!.Id}/{attachment.Id}/download");
                request.Headers.Add("X-Asdasd-Platform-Id", "av-web");
                request.Headers.Add("X-Asdasd-Platform-Version", AppInfo.GetFullVersion());

                var response = await client.SendAsync(request);
                if (response.IsSuccessStatusCode)
                {
                    var bytes = await response.Content.ReadAsByteArrayAsync();
                    await JsInteropService.DownloadFileFromStream(attachment.Filename, bytes);
                }
                else
                {
                    GlobalNotificationService.AddErrorMessage(Localizer["AttachmentDownloadFailed"], true);
                }
            }
            else
            {
                var response = await HttpClient.GetAsync($"v1/Email/{Email!.Id}/attachments/{attachment.Id}");

                if (response.IsSuccessStatusCode)
                {
                    // Get attachment bytes from API.
                    var bytes = await response.Content.ReadAsByteArrayAsync();

                    // Decrypt the attachment locally with email's encryption key.
                    var decryptedBytes = await EmailService.DecryptEmailAttachment(Email, bytes);

                    // Offer the decrypted attachment as download to the user's browser.
                    if (decryptedBytes != null)
                    {
                        await JsInteropService.DownloadFileFromStream(attachment.Filename, decryptedBytes);
                    }
                }
                else
                {
                    GlobalNotificationService.AddErrorMessage(Localizer["AttachmentDownloadFailed"], true);
                }
            }
        }
        catch (Exception ex)
        {
            GlobalNotificationService.AddErrorMessage($"{Localizer["AttachmentDownloadError"]}: {ex.Message}", true);
        }
    }
}
